import PSO from "../common/calc/pso";
import CLPSO from "../common/calc/CLPSO-deploy";
import QPSO from "../common/calc/qpso";
import BBO from "../common/calc/bbo";
import Vector from "../common/calc/vector";
import Target from "./target";
import TargetNotDisplay from "./targetNotDisplay";
import TargetGrid from "./targetGrid";
import Interferencer from "./interfer";
import deploy_const from "./constant";
import Array from "../common/utils/array_ext"
import Monitor from "./monitor";
import axios from 'axios'
import simulation from './simulation'
import moment from 'moment'
import config from './config'

// 群体类
function Flock(canvas, iteration_sum, targetNum) {
    // 获得绘图对象
    this.canvas = canvas;
    // 获得监控器对象
    this.monitor = new Monitor();
    // 群体最大迭代次数
    //this.iteration_sum = iteration_sum;
    this.iteration_sum = config.iterNum;
    //目标数量
    //this.targetNum=targetNum;
    this.targetNum=config.targetNum;
    // 群体当前迭代次数
    this.iteration = 0;
    // 网格的默认值
    this.grid = null;
    this.grid2 = null;

    // 干扰物列表
    this.inter_list = [];
    // 目标列表
    this.target_list = [];
    // 评估值变化情况
    this.evaluation = [];
    // 采用的算法
    this.algorithm = null;
    this.run = false;  // 模拟器是否开始运行
    this.gbest = {};

    // 算法名称
    //this.method = "";
    //this.method = config.method;

    // 增加网格
    this.addGrid = function (grid) {
        this.grid = grid;
    };
    this.addGrid2 = function (grid) {
        this.grid2 = grid;
    };

    // 删除网格
    this.delGrid = function () {
        if (this.grid != null) {
            // 清空目标分布的文本框
            $("#randomValue").val("");
            // 令轨迹对象为空
            this.grid = null;
        }
    };

    // 增加目标
    this.addTarget = function (target) {
        this.target_list.push(target)
    };

    // 从储存中增加目标
    // this.add_targets_from_store = function () {
    //     // 取得textarea中的值
    //     let textarea_val = document.getElementById("randomValue").value.trim();
    //     // 取得localstory中的值
    //     let local_val = localStorage.getItem(deploy_const.get("目标分布储存位置"));
    //     // 设定顺序为:1. textarea中的值, 2.localstorage, 3.随机生成
    //     if (textarea_val.length > 10) {
    //         this.string_to_targets(textarea_val);
    //         localStorage.setItem(deploy_const.get("目标分布储存位置"), textarea_val);
    //     } else if (local_val != null && local_val.length > 10) {
    //         this.string_to_targets(local_val);
    //         document.getElementById("randomValue").value = local_val;
    //     } else {
    //         this.add_all_targets();
    //     }
    // };

    this.add_targets_from_store = function () {

            this.add_all_targets();

    };


    /**
     * 根据给定的目标数,一次性随机生成指定目标
     */
    this.add_all_targets = function () {
        this.removeTargetAll();
        // 增加指定目标数量
        // let target_num = $("#target_num").val() - 0;
        // for (let i = 0; i < target_num; i++) {
        //     //let rand_x = Math.random() * this.canvas.width;
        //     //let rand_x = 216 + Math.random() * 288;
        //     let rand_x = 10 + Math.random() * 780;
        //     //let rand_y = Math.random() * this.canvas.height;
        //     let rand_y = 10 + Math.random() * 780;
        //     this.addTarget(new Target(rand_x, rand_y))
        // }

        let size = [81, 81];  // 网格点个数,例如[4,5]
        let row_num = size[0];  // 横排数量
        let column_num = size[1];  // 纵排数量
        let x_piece = 10;
        let y_piece = 10;
        // let x_coordinate = [];  // x轴坐标
        // let y_coordinate = [];  // y轴坐标
        // for (let i = 0; i < column_num + 1; i++) {
        //     x_coordinate.push(240+x_piece * i);
        // }
        // for (let i = 0; i < row_num + 1; i++) {
        //     y_coordinate.push(240+y_piece * i);
        // }

        //中心指挥所
        //this.addTarget(new Target(440, 460));
        //this.addTarget(new Target(200, 640));
        //this.addTarget(new Target(600, 200));

        //需要覆盖的目标点
        this.addTarget(new Target(240, 480));
        this.addTarget(new Target(600, 640));
        this.addTarget(new Target(640, 120));

        //边界目标点
        // for (let i = 0; i < 33; i++) {
        //     for(let j = 0; j < 33; j++){
        //         let x_g = 240+y_piece * j;
        //         let y_g = 240+x_piece * i;
        //         if(1<=j&&j<=31&&1<=i&&i<=31){
        //             continue;
        //         }else{
        //             this.addTarget(new TargetGrid(x_g, y_g));
        //         }
        //     }
        // }


        //核心区域像素目标点
        for (let i = 0; i < 33; i++) {
            for(let j = 0; j < 33; j++){
                let x_g = 240+y_piece * j;
                let y_g = 240+x_piece * i;

                    this.addTarget(new TargetNotDisplay(x_g, y_g));

            }
        }


        //外围像素目标点
        for (let i = 0; i < column_num; i++) {
            for(let j = 0; j < row_num; j++){
                let x_g = 0+y_piece * j;
                let y_g = 0+x_piece * i;
                if(24<=j&&j<=56&&24<=i&&i<=56){
                    continue;
                }else{
                    this.addTarget(new TargetNotDisplay(x_g, y_g));
                }
            }
        }

        // 将目标坐标写入textarea
        let targets_position = "";
        for (let target of this.target_list) {
            targets_position += target.toString();
        }
        document.getElementById("randomValue").value = targets_position;
        localStorage.setItem(deploy_const.get("目标分布储存位置"), targets_position);
    };

    /**
     * 将字符串转换成目标分布
     * @param info 字符串
     */
    this.string_to_targets = function (info) {
        // 首先移除所有目标
        this.removeTargetAll();
        // 将信息进行拆分
        let info_list = info.split("&#");
        let target_num = Math.floor(info_list.length / 2);
        for (let i = 0; i < target_num; i++) {
            let [x, y] = [info_list[i * 2], info_list[i * 2 + 1]];
            this.addTarget(new Target(x, y))
        }
    };

    //删除目标
    this.delTarget = function () {
        this.target_list.pop()
    };

    // 删除所有目标
    this.removeTargetAll = function () {
        this.target_list = [];
    };

    this.addInterfer = function (interfer) {
        this.inter_list.push(interfer);
    };

    this.delInterfer = function () {
        this.inter_list.pop();
    };

    this.removeInterfer = function () {
        while (this.inter_list.length > 0) {
            this.inter_list.pop()
        }
    };

    /**
     * 探测函数
     * @param dis  目标到干扰物的距离
     * @param range  干扰半径
     * @returns {number}  被探测到的系数
     */
    // this.discover_func = function (dis_list, range) {
    //     // 筛选出距离中小于干扰范围的值
    //     dis_list = dis_list.filter(x => x < range);
    //     // 如果筛选出的干扰物没有,则返回1
    //     if (dis_list.length == 0) {
    //         //return 1;//fixme
    //         //这个目标不在干扰物范围内
    //         return -0.4;
    //     } else if (dis_list.length == 1) {
    //         let dis = dis_list[0];
    //         //return (dis * dis) / (range * range);//fixme
    //         //这个目标在1个干扰物范围内
    //         return 0.3;
    //     } else if (dis_list.length > 1) {
    //         let discover_index = 1;
    //
    //         let dis_list_min = Math.min(dis_list.value);
    //         discover_index = discover_index * ((dis_list_min * dis_list_min) / (range * range));
    //
    //         // for (let dis of dis_list) {
    //         //     discover_index = discover_index * ((dis * dis) / (range * range));
    //         // }
    //
    //         //return discover_index;//fixme
    //         //这个目标在多个干扰物范围内
    //         //return 0;
    //
    //     }
    // };

    //fixme 对于每个目标而言，相当于暴露系数
    this.recover_func1 = function (dis_list, range) {
        // 筛选出距离中小于干扰范围的值
        dis_list = dis_list.filter(x => x < range);
        // 如果该目标未覆盖,则返回-2
        if (dis_list.length == 0) {
            return -2;
        } else if (dis_list.length == 1) {
            let dis = dis_list[0];
            //被1个干扰物覆盖
            return -(dis * dis) / (range * range);
            //return 1;
        } else if (dis_list.length > 1) {
            //被多个干扰物覆盖，即存在重叠覆盖
            return -1;
        }
    };
    //fixme 对于每个雷达而言，相当于保护系数
    this.recover_func2 = function (dis_list, range) {
        // 筛选出距离中小于干扰范围的值
        dis_list = dis_list.filter(x => x < range);
        // 如果该干扰物未覆盖目标,则返回0
        if (dis_list.length == 0) {
            return 0;
        } else {
            //覆盖多个目标，则需要负责多个
            return 1/dis_list.length;
        }
    };


    // fixme 评估函数,
    this.evaluate = solution => {
        // 所有目标的被发现系数
        let discover_index = 0;
        let len = solution.length;
        // 干扰器个数
        let inter_num = Math.floor(len / 2);
        // 干扰器范围
        let inter_range = document.getElementById("inter_range").value - 0;
        // 所有干扰器的列表
        let inter_list = [];
        for (let i = 0; i < inter_num; i++) {
            let inter = new Vector(solution[2 * i], solution[2 * i + 1]);
            inter_list.push(inter);
        }

        //fixme 防御效果即雷达覆盖效果，主要可以分为目标暴露系数和雷达保护系数
        for (let target of this.target_list) {
            let dis_list = inter_list.map(x => x.euc2d(target.pos));
            discover_index += this.recover_func1(dis_list, inter_range);
        }
        let target_list = [];
        for (let target of this.target_list) {
            target_list.push(target.pos);
        }
        for (let inter of inter_list) {
            let dis_list = target_list.map(x => x.euc2d(inter));
            discover_index += this.recover_func2(dis_list, inter_range);
        }

        // for (let target of this.target_list) {
        //     // 获得目标到干扰物的最近距离
        //     let target_pos = target.pos;
        //     // 获得每个干扰物到目标的距离
        //     let dis_list = inter_list.map(x => x.euc2d(target_pos));
        //     // 将单个目标被发现的系数累加到总系数中
        //     discover_index += this.discover_func(dis_list, inter_range);
        // }

        //return discover_index;
        return (-1)*discover_index;
    };


    // fixme 综合覆盖的评估函数,
    this.evaluateCover = solution => {
        // 所有目标的被发现系数
        let discover_index1 = 0;
        let discover_index2 = 0;
        let len = solution.length;
        // 干扰器个数
        let inter_num = Math.floor(len / 2);
        // 干扰器范围
        let inter_range = document.getElementById("inter_range").value - 0;
        // 所有干扰器的列表
        let inter_list = [];
        for (let i = 0; i < inter_num; i++) {
            //let inter = new Vector(solution[2 * i], solution[2 * i + 1]);

            let inter = new Interferencer(solution[2 * i], solution[2 * i + 1], inter_range);
            //let inter = new Interferencer(solution[2 * i], solution[2 * i + 1], inter_range+i*40);
            inter_list.push(inter);
        }

        //fixme 防御效果即覆盖效果，主要可以分为目标点覆盖和像素点覆盖
        //指挥所
        let dis_list0=[];
        let discover_index0 = -27;

        //for(let c = 0; c < 3; c++){
        //    for (let i = 0; i < inter_num; i++){
        //        //let dis_list1 = inter_pos.map(x => x.euc2d(this.target_list[j].pos));
        //        dis_list0.push(inter_list[i].pos.euc2d(this.target_list[c].pos));
        //        //discover_index1 += this.evaluateCover1(dis_list1, inter_list[i].range);
        //        if (dis_list0[i]<=100){
        //            discover_index0 = discover_index0+10;
        //            //break;
        //        }
        //
        //
        //    }
        //}

        //每个防御单元只能选择部署在其中的一个指挥所附近
        for(let c = 0; c < 3; c++){

                //let dis_list1 = inter_pos.map(x => x.euc2d(this.target_list[j].pos));
                dis_list0.push(inter_list[c].pos.euc2d(this.target_list[c].pos));
                //discover_index1 += this.evaluateCover1(dis_list1, inter_list[i].range);
                if (dis_list0[c]<=100){
                    discover_index0 = discover_index0+10;
                    //break;

            }
        }




        ////边界目标
        // for (let j = 3; j < 128+3; j++) {
        //核心区域
        for (let j = 0+3; j < 1089+3; j++) {
            let dis_list1=[];
            let cover=0;
            for (let i = 0; i < inter_num; i++){
                //let dis_list1 = inter_pos.map(x => x.euc2d(this.target_list[j].pos));
                dis_list1.push(inter_list[i].pos.euc2d(this.target_list[j].pos));
                //discover_index1 += this.evaluateCover1(dis_list1, inter_list[i].range);
                if (dis_list1[i]<=inter_list[i].range){
                    cover=1;
                    break;
                }
            }
            discover_index1 += cover;
        }
        ////覆盖边界目标时的外围像素点
        //for (let k = 128+3; k < 5600+3; k++) {
        //覆盖核心区域时的外围像素点
        for (let k = 1089+3; k < 6561+3; k++) {
            let dis_list2=[];
            let cover=0;
            for (let i = 0; i < inter_num; i++){
                //let dis_list2 = inter_pos.map(x => x.euc2d(this.target_list[k].pos));
                dis_list2.push(inter_list[i].pos.euc2d(this.target_list[k].pos));
                //discover_index2 += this.evaluateCover1(dis_list2, inter_list[i].range);
                if (dis_list2[i]<=inter_list[i].range){
                    cover=1;
                    break;
                }
            }
            discover_index2 += cover;
        }

        //return discover_index;//fixme
        //边界目标
        return (1-discover_index0/3)+(1-(discover_index1+discover_index2)/6561);
        //return 1-(discover_index1+discover_index2)/5600;
        //return 0.6*(1-discover_index1/128)+0.4*(1-discover_index2/5472);
        //return 0.5*(1-discover_index1/1089)+0.3*(1-discover_index2/5472);
        //return 0.9*(1-discover_index1/1089)+0.1*(1-discover_index2/5472);
        //核心区域
        //return 1-(discover_index1+discover_index2)/6561;

    };
    //fixme 对于每个目标点
    this.evaluateCover1 = function (dis_list1, range) {
        // 筛选出距离中小于干扰范围的值
        dis_list1 = dis_list1.filter(x => x < range);
        //if dis_list1
        // 如果该目标覆盖,则返回0
        if (dis_list1.length >= 0) {
            return 0;
        } else {
            return 1;

            // let b = 1;
            // for(let i = 0; i < dis_list1.length; i++){
            //     b = b*(1-Math.E ** (-(dis_list1[i]/range)));
            // }
            //
            // if((1-b)>=0.9){
            //     return 1;
            // }else{
            //     return 0;
            // }

        }
    };
    //fixme 对于每个像素点
    this.evaluateCover2 = function (dis_list2, range) {
        // 筛选出距离中小于干扰范围的值
        dis_list2 = dis_list2.filter(x => x < range);
        // 如果该目标被覆盖,则返回1
        if (dis_list2.length == 0) {
            return 0;
        } else {

            return 1;
        }
    };


    // fixme 暴露率的评估函数
    this.evaluateExposeIndex = (solution)=>{
        // 计算单个雷达对目标的隐藏率
        const _calcSoloExposeIndex = (dis, inter_range)=>{
            const exposeLevel = 1  // 暴露率参数
            //return Math.E ** (exposeLevel * ((dis/inter_range)-1))
            return 1-(1-dis/inter_range)**2 //视觉传感器
            //return 1-
        }
        // 计算雷达群对目标的隐藏率
        const _getExposeIndex = (dis_list, interRange)=>{
            // 获得所有在雷达有效范围的距离, 求得有效雷达数量
            const inRangeDis = dis_list.filter(dis=>dis<interRange)
            const radarNum = inRangeDis.length
            // 如果没有雷达, 则暴露值为0
            if(radarNum === 0){
                return 100
            }else if(radarNum === 1){
                // 如果只有一个雷达, 则直接计算
                return _calcSoloExposeIndex(inRangeDis[0], interRange)
            }else if (radarNum > 1){
                // 如果不止一个雷达, 则找到最近的距离,再进行处理
                inRangeDis.sort((a,b)=>a-b)
                // 找到最近的距离
                let nearestRadar = inRangeDis[0]
                inRangeDis.forEach((dis, index)=>{
                    if(index !== 0){
                        nearestRadar += 1/(inRangeDis.length-1)*(interRange-dis)
                        //nearestRadar += -dis
                    }
                })
                return _calcSoloExposeIndex(nearestRadar, interRange)
            }
        }

        let ExposeNum = 0;  // 总暴露值
        let len = solution.length;
        // 干扰器个数
        let inter_num = Math.floor(len / 2);
        // 干扰器范围
        let interRange = document.getElementById("inter_range").value - 0;
        // 所有干扰器的列表
        let interList = [];
        for (let i = 0; i < inter_num; i++) {
            let inter = new Vector(solution[2 * i], solution[2 * i + 1]);
            interList.push(inter);
        }

        for (let target of this.target_list) {
            // 获得目标到干扰物的最近距离
            let target_pos = target.pos;
            // 获得每个干扰物到目标的距离
            let disList = interList.map(x => x.euc2d(target_pos));
            // 将单个目标被发现的系数累加到总系数中
            ExposeNum += _getExposeIndex(disList, interRange);
        }
        return ExposeNum/this.targetNum;
    }


    //this.setConfig(config){
    //    this.config = config;
    //    this.method = config.method;
    //}

    // 设置算法情况
    this.set_algorithm = function (config) {
        // 干扰物数量
        let inter_num = document.getElementById("inter_num").value - 0;
        let method=config.method;

        if (inter_num > 0) {
            let dimension = inter_num * 2;
            let ub = [this.canvas.width, this.canvas.height].repeat(inter_num);
            let lb = [0, 0].repeat(inter_num);

            if (method === "BBO") {
                console.log("使用BBO算法");
                this.algorithm = new BBO(dimension, ub, lb, this.evaluateCover, config.particleNum, config.iterNum);
            } else if (method === "PSO") {
                console.log("使用PSO算法");
                this.algorithm = new PSO(dimension, ub, lb, this.evaluateCover, config.particleNum, config.iterNum);
            } else if (method === "CLPSO") {
                console.log("使用CLPSO算法");
                //this.algorithm = new CLPSO(dimension, ub, lb, this.evaluateExposeIndex, config.particleNum, config.iterNum);
                //evaluateCover
                this.algorithm = new CLPSO(dimension, ub, lb, this.evaluateCover, config.particleNum, config.iterNum);
            } else if (method === "QPSO") {
                console.log("使用QPSO算法");
                this.algorithm = new QPSO(dimension, ub, lb, this.evaluateCover, config.particleNum, config.iterNum);
            }
        }
    };

    // 更新数据方法
    this.update = function () {
        const generateSaveData = ()=>{
            const saveData = {}
            saveData["saveTime"] = moment().format('YYYY-MM-DD HH:mm:ss')
            //saveData['method'] = this.method
            saveData['gbestValue'] = this.algorithm.gbestValue
            saveData["Distribution"] = this.inter_list
            saveData["config"] = config
            //saveData["targetDistribution"] = this.target_list
            //saveData['gbest'] = this.gbest
            //saveData["evaluation"] = this.evaluation
            saveData["evaluateExposeIndex"] = this.evaluation

            return saveData
        }

        // 初始化计算方法
        if (this.algorithm === null) {
            this.set_algorithm(config);
        }
        // 如果迭代未完成,则每次全局迭代数+1
        if (this.iteration < this.iteration_sum) {
            this.iteration++;
            if (this.iteration % 10 === 0) {
                const {currentStep, gbest, gbestValue} = this.algorithm.step_run(10);
                //const [gbest, gbest_value] = this.algorithm.step_run(50);
                this.set_refer(gbest);
                this.monitor.update_data(gbestValue, 10);
                this.evaluation.push({iter: this.iteration, gbestValue: gbestValue.toFixed(3)})
                this.gbest = gbest
                this.monitor.show();
            }
        } else {
            this.run = false
            axios.post("http://localhost:3001/saveDeploy",{
                id: "测试数据",
                data: JSON.stringify(generateSaveData())
            }).then(
                (response)=>{
                    setTimeout(function(){
                        location.reload();
                    },5000)
                }
            ).catch((error)=>{
                console.log("失败",error)
            })
        }

    };

    /**
     * 根据解的情况绘制干扰物
     * @param solution
     */
    this.set_refer = function (solution) {
        // 清空干扰物
        this.removeInterfer();
        let inter_range = document.getElementById("inter_range").value - 0;
        let len = solution.length;
        //let len = ;
            // 干扰器个数
        let inter_num = Math.floor(len / 2);
        // 所有干扰器的列表
        let inter_list = [];
        for (let i = 0; i < inter_num; i++) {
            //let inter = new Interferencer(solution[2 * i], solution[2 * i + 1], inter_range+i*40);
            let inter = new Interferencer(solution[2 * i], solution[2 * i + 1], inter_range);
            this.addInterfer(inter);
        }
    };

    // 整个群体的绘图方法
    this.draw = function (ctx, width, height) {
        let i;
        let accSpeed = 0;  // 速度的累加值
        let speeds = [];
        // 绘制网格
        if (this.grid !== null) {
            this.grid.draw(ctx);
        }
        if (this.grid2 !== null) {
            this.grid2.draw(ctx);
        }

        //fixme  绘制目标：核心区1089，边界128
        for (let i = 0; i < 3; i++) {
            this.target_list[i].draw(ctx);
        }
        //  绘制干扰物
        for (let i = 0; i < this.inter_list.length; i++) {
            this.inter_list[i].draw(ctx);
        }
    }
}

export default Flock;